package me.flyray.crm.core.biz;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.wxiaoqi.security.auth.common.util.SnowFlake;
import com.github.wxiaoqi.security.biz.common.crm.request.IntoAccountRequest;
import com.github.wxiaoqi.security.biz.common.msg.BizResponseCode;
import com.github.wxiaoqi.security.common.enums.AccountStateEnums;
import com.github.wxiaoqi.security.common.enums.CustomerTypeEnums;
import com.github.wxiaoqi.security.common.enums.InOutFlagEnums;
import com.github.wxiaoqi.security.common.util.CurrencyUtils;
import com.github.wxiaoqi.security.common.util.EntityUtils;
import com.github.wxiaoqi.security.common.util.MD5;

import lombok.extern.slf4j.Slf4j;
import me.flyray.crm.core.entity.MerchantAccount;
import me.flyray.crm.core.entity.MerchantAccountJournal;
import me.flyray.crm.core.entity.PersonalAccount;
import me.flyray.crm.core.entity.PersonalAccountJournal;
import me.flyray.crm.core.entity.PersonalBase;
import me.flyray.crm.core.entity.PlatformAccoutConfig;
import me.flyray.crm.core.mapper.MerchantAccountJournalMapper;
import me.flyray.crm.core.mapper.MerchantAccountMapper;
import me.flyray.crm.core.mapper.PersonalAccountJournalMapper;
import me.flyray.crm.core.mapper.PersonalAccountMapper;
import me.flyray.crm.core.mapper.PersonalBaseMapper;
import me.flyray.crm.core.mapper.PlatformAccoutConfigMapper;

/**
 * 入账相关的操作
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@Service
public class CommonIntoAccountBiz {

	@Value("${bountyHunter.balanceSaltValue}")
	private String balanceSaltValue;
	@Autowired
	private MerchantAccountMapper merAccountMapper;
	@Autowired
	private PersonalAccountMapper personalAccountMapper;
	@Autowired
	private PersonalAccountJournalMapper personalAccountJournalMapper;
	@Autowired
	private PersonalBaseMapper personalBaseMapper;
	@Autowired
	private MerchantAccountJournalMapper merchantAccountJournalMapper;
	@Autowired
	private PlatformAccoutConfigMapper platformAccoutConfigMapper;
	/**
	 * 个人或者商户入账相关的接口: 
	 * 若是商户账户： 
	 * 1、商户账号入账 
	 * 2、新增商户账户流水记录
	 * 若是个人账户： 
	 * 1、个人账户入账
	 * 2、新增个人账户流水记录
	 */
	public Map<String, Object> intoAccount(IntoAccountRequest intoAccountRequest) {
		log.info("个人或者商户入账相关的接口 请求参数：{}" + EntityUtils.beanToMap(intoAccountRequest));
		Map<String, Object> response = new HashMap<String, Object>();
		//商户入账
		if (intoAccountRequest.getCustomerType().equals(CustomerTypeEnums.CUST_MERCHANT.getCode())) {
			MerchantAccount queryAccount = new MerchantAccount();
			queryAccount.setPlatformId(intoAccountRequest.getPlatformId());
			queryAccount.setMerchantId(intoAccountRequest.getMerchantId());
			queryAccount.setMerchantType(intoAccountRequest.getMerchantType());
			queryAccount.setAccountType(intoAccountRequest.getAccountType());
			MerchantAccount merchantAccount = merAccountMapper.selectOne(queryAccount);
			String accountId = "";
			if (null == merchantAccount) {// 商户账号还未开户
				/**
				 * 商户账号开通
				 */
				PlatformAccoutConfig queryaccoutConfig=new PlatformAccoutConfig();
				queryaccoutConfig.setPlatformId(intoAccountRequest.getPlatformId());
				queryaccoutConfig.setCustomerType(intoAccountRequest.getMerchantType());
				queryaccoutConfig.setAccountType(intoAccountRequest.getAccountType());
				PlatformAccoutConfig accoutConfig =platformAccoutConfigMapper.selectOne(queryaccoutConfig);
				if(null==accoutConfig){//平台支持的账户类型不存在 就没法开户
					response.put("code", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getCode());
					response.put("message", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getMessage());
					log.info("个人或者商户入账相关的接口-返回参数。。。。。。{}", response);
					return response;
				}
				MerchantAccount newAccount = new MerchantAccount();
				accountId = String.valueOf(SnowFlake.getId());
				newAccount.setAccountId(accountId);
				newAccount.setPlatformId(intoAccountRequest.getPlatformId());
				newAccount.setMerchantId(intoAccountRequest.getMerchantId());
				newAccount.setMerchantType(intoAccountRequest.getMerchantType());
				newAccount.setAccountType(intoAccountRequest.getAccountType());
				newAccount.setCcy("CNY");
				newAccount.setFreezeBalance(BigDecimal.ZERO);
				newAccount.setAccountBalance(new BigDecimal(intoAccountRequest.getIntoAccAmt()));
				newAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(newAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
				newAccount.setStatus(AccountStateEnums.normal.getCode());
				newAccount.setCreateTime(new Date());
				merAccountMapper.insertSelective(newAccount);
			}else{
				if (null != merchantAccount && AccountStateEnums.normal.getCode().equals(merchantAccount.getStatus())) {
					if (!MD5.sign(CurrencyUtils.decimaltoString(merchantAccount.getAccountBalance()), balanceSaltValue, "utf-8").equals(merchantAccount.getCheckSum())) {
						response.put("code", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getCode());
						response.put("message", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getMessage());
						log.info("入账（第三方支付）返回参数。。。。。。{}", response);
						return response;
					}
					merchantAccount.setAccountBalance(merchantAccount.getAccountBalance().add(new BigDecimal(intoAccountRequest.getIntoAccAmt())));
					merchantAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(merchantAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
					merchantAccount.setUpdateTime(new Date());
					merAccountMapper.updateByPrimaryKeySelective(merchantAccount);
				} else {
					response.put("code", BizResponseCode.MER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.MER_ACC_FREEZE.getMessage());
					log.info("个人或者商户入账相关的接口 返回参数。。。。。。{}", response);
					return response;
				}
				if (StringUtils.isEmpty(accountId)) {
					accountId = merchantAccount.getAccountId();
				}
			}

			//补充，如果是余额账户入账，记录手续费账户和可提现余额账户
			if("ACC001".equals(intoAccountRequest.getAccountType()) && !StringUtils.isEmpty(intoAccountRequest.getTxFee())){
				BigDecimal txFee = new BigDecimal(intoAccountRequest.getTxFee());
				if(BigDecimal.ZERO.compareTo(txFee) < 0){
					//手续费账户
					MerchantAccount feeAccount = new MerchantAccount();
					feeAccount.setPlatformId(intoAccountRequest.getPlatformId());
					feeAccount.setMerchantId(intoAccountRequest.getMerchantId());
					feeAccount.setMerchantType(intoAccountRequest.getMerchantType());
					feeAccount.setAccountType("ACC004");//手续费账户
					MerchantAccount queryFeeAccount = merAccountMapper.selectOne(feeAccount);
					if(null == queryFeeAccount){
						accountId = String.valueOf(SnowFlake.getId());
						feeAccount.setAccountId(accountId);
						feeAccount.setCcy("CNY");
						feeAccount.setFreezeBalance(BigDecimal.ZERO);
						feeAccount.setAccountBalance(txFee);
						feeAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(txFee), balanceSaltValue, "utf-8"));
						feeAccount.setStatus(AccountStateEnums.normal.getCode());
						feeAccount.setCreateTime(new Date());
						merAccountMapper.insertSelective(feeAccount);
					}else{
						queryFeeAccount.setAccountBalance(queryFeeAccount.getAccountBalance().add(txFee));
						queryFeeAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(queryFeeAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
						merAccountMapper.updateByPrimaryKeySelective(queryFeeAccount);
					}

				}
				if(org.springframework.util.StringUtils.isEmpty(intoAccountRequest.getTxFee())){
					txFee = BigDecimal.ZERO;
				}else{
					txFee = new BigDecimal(intoAccountRequest.getTxFee());
				}
				//可提现余额账户
				MerchantAccount payForAnotherAccount = new MerchantAccount();
				payForAnotherAccount.setPlatformId(intoAccountRequest.getPlatformId());
				payForAnotherAccount.setMerchantId(intoAccountRequest.getMerchantId());
				payForAnotherAccount.setMerchantType(intoAccountRequest.getMerchantType());
				payForAnotherAccount.setAccountType("ACC013");//可提现余额账户
				MerchantAccount queryPayForAnotherAccount = merAccountMapper.selectOne(payForAnotherAccount);
				BigDecimal intoAccAmt = new BigDecimal(intoAccountRequest.getIntoAccAmt());
				if(null == queryPayForAnotherAccount){
					accountId = String.valueOf(SnowFlake.getId());
					payForAnotherAccount.setAccountId(accountId);
					payForAnotherAccount.setCcy("CNY");
					payForAnotherAccount.setFreezeBalance(BigDecimal.ZERO);
					payForAnotherAccount.setAccountBalance(intoAccAmt.subtract(txFee));
					payForAnotherAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(payForAnotherAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
					payForAnotherAccount.setStatus(AccountStateEnums.normal.getCode());
					payForAnotherAccount.setCreateTime(new Date());
					merAccountMapper.insertSelective(payForAnotherAccount);
				}else{
					queryPayForAnotherAccount.setAccountBalance(queryPayForAnotherAccount.getAccountBalance().add(intoAccAmt.subtract(txFee)));
					queryPayForAnotherAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(queryPayForAnotherAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
					merAccountMapper.updateByPrimaryKeySelective(queryPayForAnotherAccount);
				}
			}

			MerchantAccountJournal merAccountJournal = new MerchantAccountJournal();
			merAccountJournal.setJournalId(String.valueOf(SnowFlake.getId()));
			merAccountJournal.setPlatformId(intoAccountRequest.getPlatformId());
			merAccountJournal.setMerchantId(intoAccountRequest.getMerchantId());
			merAccountJournal.setAccountId(accountId);
			merAccountJournal.setAccountType(intoAccountRequest.getAccountType());
			merAccountJournal.setOrderNo(intoAccountRequest.getOrderNo());
			merAccountJournal.setInOutFlag(InOutFlagEnums.in.getCode());
			merAccountJournal.setTradeAmt(new BigDecimal(intoAccountRequest.getIntoAccAmt()));
			merAccountJournal.setTradeType(intoAccountRequest.getTradeType());
			merAccountJournal.setCreateTime(new Date());
			merchantAccountJournalMapper.insertSelective(merAccountJournal);
			response.put("code", BizResponseCode.OK.getCode());
			response.put("message", BizResponseCode.OK.getMessage());
		}

		//个人入账
		if (intoAccountRequest.getCustomerType().equals(CustomerTypeEnums.CUST_PERSONAL.getCode())) {
			if ("05".equals(intoAccountRequest.getTradeType())) {
				//发表说说每天领取两次
				Map<String, Object> jorunalReq = new HashMap<>();
				jorunalReq.put("platformId", intoAccountRequest.getPlatformId());
				jorunalReq.put("personalId", intoAccountRequest.getPersonalId());
				int revCount = personalAccountJournalMapper.queryPersonalAccountJournalCount(jorunalReq);
				log.info("个人或者商户入账相关的接口 发表说说领取原力值次数== "+revCount);
				if (revCount >= 2) {
					log.info("个人或者商户入账相关的接口 返回参数。。。。。。当天已经领取两次{}", BizResponseCode.REV_COUNT_OVER.getMessage());
					response.put("code", BizResponseCode.REV_COUNT_OVER.getCode());
					response.put("message", BizResponseCode.REV_COUNT_OVER.getMessage());
					return response;
				}
			}
			PersonalBase base = new PersonalBase();
			base.setPersonalId(intoAccountRequest.getPersonalId());
			PersonalBase reult = personalBaseMapper.selectOne(base);
			if (null == reult) {
				log.info("个人或者商户入账相关的接口 返回参数。。。。。。个人客户信息不存在");
				response.put("code", BizResponseCode.PER_NOTEXIST.getCode());
				response.put("message", BizResponseCode.PER_NOTEXIST.getMessage());
				return response;
			}
			String perAccountId = "";
			PersonalAccount queryPerAccountparam=new PersonalAccount();
			queryPerAccountparam.setPlatformId(intoAccountRequest.getPlatformId());
			queryPerAccountparam.setPersonalId(intoAccountRequest.getPersonalId());
			queryPerAccountparam.setAccountType(intoAccountRequest.getAccountType());
			PersonalAccount personalAccount=personalAccountMapper.selectOne(queryPerAccountparam);
			String accountType = null;
			if(null==personalAccount){
				PlatformAccoutConfig queryaccoutConfig=new PlatformAccoutConfig();
				queryaccoutConfig.setPlatformId(intoAccountRequest.getPlatformId());
				queryaccoutConfig.setCustomerType(intoAccountRequest.getMerchantType());
				queryaccoutConfig.setAccountType(intoAccountRequest.getAccountType());
				PlatformAccoutConfig accoutConfig =platformAccoutConfigMapper.selectOne(queryaccoutConfig);
				if(null==accoutConfig){//平台支持的账户类型不存在 就没法开户
					response.put("code", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getCode());
					response.put("message", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getMessage());
					log.info("个人或者商户入账相关的接口-返回参数。。。。。。{}", response);
					return response;
				}
				PersonalAccount newPerAcc= new PersonalAccount();
				perAccountId = String.valueOf(SnowFlake.getId());
				newPerAcc.setAccountId(perAccountId);
				newPerAcc.setPlatformId(intoAccountRequest.getPlatformId());
				newPerAcc.setPersonalId(intoAccountRequest.getPersonalId());
				newPerAcc.setAccountType(intoAccountRequest.getAccountType());
				newPerAcc.setCcy("CNY");
				newPerAcc.setAccountBalance(new BigDecimal(intoAccountRequest.getIntoAccAmt()));
				newPerAcc.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(newPerAcc.getAccountBalance()), balanceSaltValue, "utf-8"));
				newPerAcc.setFreezeBalance(BigDecimal.ZERO);
				newPerAcc.setStatus(AccountStateEnums.normal.getCode());
				newPerAcc.setCreateTime(new Date());
				personalAccountMapper.insertSelective(newPerAcc);
				accountType = intoAccountRequest.getAccountType();
			}else{
				if (null != personalAccount && AccountStateEnums.normal.getCode().equals(personalAccount.getStatus())) {

					BigDecimal b = personalAccount.getAccountBalance();
					if (!MD5.sign(CurrencyUtils.decimaltoString(b), balanceSaltValue, "utf-8").equals(personalAccount.getCheckSum())) {
						response.put("code", BizResponseCode.PER_ACC_BALANCE_NOT_MATE.getCode());
						response.put("message", BizResponseCode.PER_ACC_BALANCE_NOT_MATE.getMessage());
						log.info("入账（第三方支付）返回参数。。。。。。{}", response);
						return response;
					}
					personalAccount.setUpdateTime(new Date());
					personalAccount.setAccountBalance(personalAccount.getAccountBalance().add(new BigDecimal(intoAccountRequest.getIntoAccAmt())));
					personalAccount.setCheckSum(MD5.sign(CurrencyUtils.decimaltoString(personalAccount.getAccountBalance()), balanceSaltValue, "utf-8"));
					personalAccountMapper.updateByPrimaryKeySelective(personalAccount);
				} else {
					response.put("code", BizResponseCode.PER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.PER_ACC_FREEZE.getMessage());
					log.info("个人或者商户入账相关的接口 返回参数。。。。。。{}", response);
					return response;
				}
				if (StringUtils.isEmpty(perAccountId)) {
					perAccountId = personalAccount.getAccountId();
				}
				accountType = personalAccount.getAccountType();
			}

			PersonalAccountJournal personalAccountJournal=new PersonalAccountJournal();
			personalAccountJournal.setJournalId(String.valueOf(SnowFlake.getId()));
			personalAccountJournal.setPlatformId(intoAccountRequest.getPlatformId());
			personalAccountJournal.setPersonalId(intoAccountRequest.getPersonalId());
			personalAccountJournal.setAccountId(perAccountId);
			personalAccountJournal.setAccountType(accountType);
			personalAccountJournal.setOrderNo(intoAccountRequest.getOrderNo());
			personalAccountJournal.setInOutFlag(InOutFlagEnums.in.getCode());//来往标志  1：来账   2：往账
			personalAccountJournal.setTradeAmt(new BigDecimal(intoAccountRequest.getIntoAccAmt()));
			personalAccountJournal.setTradeType(intoAccountRequest.getTradeType());//交易类型// 01：支付，02：退款，03：提现，04：充值，05：预收款，06：消费，07：结算，08：领取
			personalAccountJournal.setCreateTime(new Date());
			personalAccountJournalMapper.insertSelective(personalAccountJournal);
			response.put("code", BizResponseCode.OK.getCode());
			response.put("message", BizResponseCode.OK.getMessage());
		}
		return response;
	}


}
